"""
DSL解释器核心
负责执行解析后的DSL脚本，处理用户交互和状态管理
重新设计，确保能正确查找和执行嵌套规则
"""

import uuid
import os
from datetime import datetime
from typing import Dict, List, Any, Optional
import re
from src.models.data_models import Order, Vars, UserSession, create_default_hardware_orders
from src.core.dsl_parser import DSLAnalyzer
from src.core.llm_client import LLMClient


class DSLInterpreter:
    """DSL解释器类 - 重新设计，确保嵌套规则正确执行"""
    
    def __init__(self, llm_client: LLMClient = None, data_file: str = 'user_data.json'):
        """
        初始化解释器
        
        Args:
            llm_client: LLM客户端实例
            data_file: 用于持久化用户数据的文件路径
        """
        self.analyzer = DSLAnalyzer()
        self.llm_client = llm_client or LLMClient()
        self.user_session = UserSession()
        self.data_file = data_file
        self.script_rules = []
        self.conversation_history = []
        self.longmemory = []
        self.hardware_orders = create_default_hardware_orders()
        self._last_user_input = ""
        self._last_extracted_order_id = None
        
        self._load_or_initialize_sessions()
    
    def _load_or_initialize_sessions(self):
        """加载用户会话数据，如果文件不存在则初始化并保存"""
        self.user_session.load_from_file(self.data_file)
        if not self.user_session.sessions:
            # 如果加载失败或文件为空，则创建预设用户并保存
            self._init_predefined_users()
            self.user_session.save_to_file(self.data_file)

    def _init_predefined_users(self):
        """初始化预置用户 fusihan1/2/3 以及各自的订单"""
        predefined = {
            'fusihan1': [
                Order("F1-001", "CS手机一号", 4999, "2025-01-10", "已付款"),
                Order("F1-002", "CS电脑二号", 8999, "2025-01-18", "待付款"),
            ],
            'fusihan2': [
                Order("F2-101", "CS平板一号", 2999, "2025-02-02", "已付款"),
                Order("F2-102", "CS耳机三号", 1299, "2025-02-05", "已付款"),
                Order("F2-103", "CS手机三号", 5999, "2025-02-12", "待付款"),
            ],
            'fusihan3': [
                Order("F3-201", "CS电脑一号", 6999, "2025-03-03", "已付款"),
            ]
        }
        for uname, orders in predefined.items():
            if not self.user_session.get_session(uname):
                uv = self.user_session.create_session(uname, "default_password")
                for od in orders:
                    uv.add_order(od)
                self.user_session.update_session(uname, uv)

    def get_hardware_orders(self) -> List[Order]:
        """获取当前系统内存中的硬件订单列表"""
        return list(self.hardware_orders)

    def reset_hardware_orders(self):
        """重新加载默认硬件订单（用于测试或重置场景）"""
        self.hardware_orders = create_default_hardware_orders()

    def _remove_hardware_order(self, order_id: str):
        """从系统硬件订单中移除指定订单（用于未付款订单取消场景）"""
        if not order_id:
            return
        self.hardware_orders = [order for order in self.hardware_orders if order.order_id != order_id]

    def load_script(self, script_text: str) -> bool:
        """
        加载DSL脚本
        
        Args:
            script_text: DSL脚本文本
            
        Returns:
            是否加载成功
        """
        parsed_script = self.analyzer.parse(script_text)
        if parsed_script:
            self.script_rules = self.analyzer.get_intent_rules()
            return True
        return False
    
    def process_user_input(self, user_name: str, user_input: str) -> str:
        """
        处理用户输入
        
        Args:
            user_name: 用户名
            user_input: 用户输入
            
        Returns:
            机器人回复
        """
        self._last_user_input = user_input
        user_vars = self.user_session.get_session(user_name)
        if not user_vars:
            user_vars = self.user_session.create_session(user_name, "default_password")
        
        self.conversation_history.append({
            'user': user_name,
            'input': user_input,
            'timestamp': datetime.now().isoformat()
        })
        self._add_to_longmemory('user', user_input, user_name)
        
        intent = self.llm_client.recognize_intent(user_input)
        current_state = user_vars.get_state()

        if intent.lower() in ['order_cancel', '订单取消']:
            extracted_id = self._extract_order_id(user_input, user_vars)
            if extracted_id:
                action = {
                    'type': 'order',
                    'operation': {'op_type': 'cancel', 'target': extracted_id}
                }
                response = self._execute_order_operation(user_vars, action)
                response = self._sanitize_response(response)
                self.user_session.update_session(user_name, user_vars)
                self.user_session.save_to_file(self.data_file) # Persist changes
                self.conversation_history.append({'bot': True, 'response': response, 'timestamp': datetime.now().isoformat()})
                self._add_to_longmemory('assistant', response)
                return response
        
        if current_state and current_state.upper() == 'COMPLAINT_HANDLING' or intent.lower() in ['complaint', '投诉']:
            text = user_input.strip().lower()
            if ('转人工' in user_input) or ('人工客服' in user_input) or ('转接客服' in user_input):
                user_vars.set_manual_transfer(True)
                user_vars.set_state('MANUAL_HANDOVER')
                response = "已为您转接人工客服，请稍候，稍后将有客服人员与您联系。"
                self.user_session.update_session(user_name, user_vars)
                self.user_session.save_to_file(self.data_file)
                self.conversation_history.append({'bot': True, 'response': response, 'timestamp': datetime.now().isoformat()})
                self._add_to_longmemory('assistant', response)
                return response
            if ('技术问题' in user_input) or ('技术' in user_input and '问题' in user_input):
                user_vars.set_complaint_category('technical')
                response = (
                    "已记录为技术问题。请提供：\n"
                    "1. 设备型号与序列号\n"
                    "2. 具体报错现象/截图/视频\n"
                    "3. 发生频率与触发步骤\n"
                    "4. 您已尝试的处理方式"
                )
                self.user_session.update_session(user_name, user_vars)
                self.user_session.save_to_file(self.data_file)
                self.conversation_history.append({'bot': True, 'response': response, 'timestamp': datetime.now().isoformat()})
                self._add_to_longmemory('assistant', response)
                return response
            if ('服务问题' in user_input) or ('服务' in user_input and '问题' in user_input):
                user_vars.set_complaint_category('service')
                response = (
                    "已记录为服务问题。请提供：\n"
                    "1. 涉及环节（下单/发货/配送/售后/客服等）\n"
                    "2. 发生时间与相关订单号（如有）\n"
                    "3. 具体问题描述与影响\n"
                    "4. 您期望的解决方案"
                )
                self.user_session.update_session(user_name, user_vars)
                self.user_session.save_to_file(self.data_file)
                self.conversation_history.append({'bot': True, 'response': response, 'timestamp': datetime.now().isoformat()})
                self._add_to_longmemory('assistant', response)
                return response

        state_rule = self._find_state_rule_with_when(current_state, intent)
        if state_rule:
            response = self._execute_state_when_rule(user_vars, state_rule, intent)
            if response:
                response = self._extract_specific_product_response(user_input, intent, response)
                self.user_session.update_session(user_name, user_vars)
                self.user_session.save_to_file(self.data_file)
                self.conversation_history.append({
                    'bot': True,
                    'response': response,
                    'timestamp': datetime.now().isoformat()
                })
                self._add_to_longmemory('assistant', response)
                return response
        
        intent_lower = intent.lower()
        nested_rule = self._find_nested_rule(intent)
        if nested_rule:
            parent_rule = nested_rule['parent_rule']
            when_action = nested_rule['when_action']
            
            for action in parent_rule.get('actions', []):
                action_type = action.get('type')
                if action_type not in ['respond', 'when_respond', 'when_action']:
                    self._execute_action(user_vars, action)
            
            if when_action.get('type') == 'when_respond':
                response = when_action.get('content', '')
                response = self._extract_specific_product_response(user_input, intent, response)
            elif when_action.get('type') == 'when_action':
                nested_actions = when_action.get('actions', [])
                response_parts = []
                
                for nested_action in nested_actions:
                    if nested_action.get('type') == 'respond':
                        content = nested_action.get('content', '')
                        content = self._extract_specific_product_response(user_input, intent, content)
                        response_parts.append(content)
                    elif nested_action.get('type') == 'when_respond':
                        if nested_action.get('intent', '').lower() == intent_lower:
                            content = nested_action.get('content', '')
                            content = self._extract_specific_product_response(user_input, intent, content)
                            response_parts.append(content)
                    else:
                        result = self._execute_action(user_vars, nested_action)
                        if result:
                            response_parts.append(result)
                
                response = " ".join(response_parts) if response_parts else ""
            else:
                response = ""
            
            if not response:
                response = "好的，我明白了。"
        else:
            rule = self.analyzer.get_rule_by_intent(intent)
            
            if rule:
                response = self._execute_actions(user_vars, rule['actions'])
                response = self._extract_specific_product_response(user_input, intent, response)
            else:
                response = self._get_default_response_for_intent(intent, user_input)

        response = self._sanitize_response(response)
        
        self.user_session.update_session(user_name, user_vars)
        self.user_session.save_to_file(self.data_file)
        
        self.conversation_history.append({
            'bot': True,
            'response': response,
            'timestamp': datetime.now().isoformat()
        })
        self._add_to_longmemory('assistant', response)
        
        return response
    
    def _execute_actions(self, user_vars: Vars, actions: List[Dict]) -> str:
        """
        执行动作列表
        """
        response_parts = []
        for action in actions:
            result = self._execute_action(user_vars, action)
            if result:
                response_parts.append(result)
        return " ".join(response_parts) if response_parts else "好的，我明白了。"
    
    def _execute_action(self, user_vars: Vars, action: Dict) -> str:
        """
        执行单个动作
        """
        action_type = action.get('type')
        if action_type == 'set_state':
            return self._execute_set_state(user_vars, action)
        elif action_type == 'order':
            return self._execute_order_operation(user_vars, action)
        elif action_type == 'respond':
            return self._execute_respond(action)
        elif action_type == 'condition':
            return self._execute_condition(user_vars, action)
        return ""
    
    def _execute_set_state(self, user_vars: Vars, action: Dict) -> str:
        """执行状态设置动作"""
        state = action.get('state')
        user_vars.set_state(state)
        return ""

    def _extract_order_id(self, text: str, user_vars: Vars) -> Optional[str]:
        """从自然语言中抽取订单号"""
        if not text:
            return None
        for od in user_vars.get_order_list():
            if od.order_id and od.order_id in text:
                return od.order_id
        patterns = [
            r'(ORD\d{3,})', r'(F\d-\d{3,})', r'(HW-[A-Z0-9-]{3,})', r'([A-Z]{2,}-\d{3,})'
        ]
        for pat in patterns:
            m = re.search(pat, text, re.IGNORECASE)
            if m:
                return m.group(1)
        return None
    
    def _execute_order_operation(self, user_vars: Vars, action: Dict) -> str:
        """执行订单操作"""
        operation = action.get('operation')
        op_type = operation.get('op_type')
        
        if op_type == 'create':
            params = operation.get('params')
            order_id = str(uuid.uuid4())[:8]
            order = Order(
                order_id=order_id,
                order_name=params['product_name'],
                order_amount=params['amount'],
                order_date=params['date']
            )
            user_vars.add_order(order)
            return f"订单创建成功，订单号: {order_id}"
            
        elif op_type == 'cancel':
            target_order_id = operation.get('target')
            order = user_vars.find_order_by_id(target_order_id)
            if order:
                if order.order_status in ['未付款', '待付款']:
                    user_vars.remove_order(target_order_id)
                    self._remove_hardware_order(target_order_id)
                    return f"订单 {target_order_id} 已取消。"
                else:
                    return f"订单 {target_order_id} 已付款，无法直接取消。如需退款，请回复‘申请退款’。"
            else:
                return f"未找到订单 {target_order_id}"
                
        elif op_type == 'check':
            target_order_id = operation.get('target')
            order = user_vars.find_order_by_id(target_order_id)
            if order:
                return str(order)
            else:
                return f"未找到订单 {target_order_id}"
                
        elif op_type == 'list':
            orders = user_vars.get_order_list()
            if orders:
                order_list = "\n".join([str(o) for o in orders])
                return f"您的订单列表:\n{order_list}"
            else:
                return "您还没有任何订单"
        
        return ""
    
    def _execute_respond(self, action: Dict) -> str:
        """执行回复动作"""
        return action.get('content', '')
    
    def _execute_condition(self, user_vars: Vars, action: Dict) -> str:
        """执行条件动作"""
        condition = action.get('condition')
        condition_type = condition.get('type')
        condition_result = False
        
        if condition_type == 'comparison':
            left = condition.get('left')
            right = condition.get('right')
            if left == 'user_state':
                condition_result = user_vars.get_state() == right
            elif left == 'order_exists':
                order = user_vars.find_order_by_id(right)
                condition_result = order is not None
        elif condition_type == 'boolean':
            value = condition.get('value')
            if value == 'user_authenticated':
                condition_result = True
        
        if condition_result:
            return self._execute_actions(user_vars, action.get('then_actions', []))
        else:
            return self._execute_actions(user_vars, action.get('else_actions', []))
    
    def _find_state_rule_with_when(self, state: str, intent: str) -> Optional[Dict]:
        """查找包含状态内 WHEN 规则的规则"""
        if not state or not intent:
            return None
        for rule in self.script_rules:
            has_state = False
            for action in rule.get('actions', []):
                if action.get('type') == 'set_state' and action.get('state') == state:
                    has_state = True
                    break
            if has_state:
                for when_action in rule.get('actions', []):
                    if when_action.get('type') in ['when_respond', 'when_action']:
                        if self._match_intent(when_action.get('intent'), intent):
                            return rule
        return None
    
    def _find_nested_rule(self, intent: str) -> Optional[Dict]:
        """查找嵌套规则"""
        if not intent:
            return None
        intent_lower = intent.lower()
        sub_intents = ['computer', 'phone', 'pad', 'earset']
        if intent_lower not in sub_intents:
            return None
        
        def find_in_actions(actions: List[Dict], parent_rule: Dict) -> Optional[Dict]:
            for action in actions:
                if action.get('type') in ['when_respond', 'when_action']:
                    if action.get('intent', '').lower() == intent_lower:
                        return {'parent_rule': parent_rule, 'when_action': action}
                    if action.get('type') == 'when_action':
                        result = find_in_actions(action.get('actions', []), parent_rule)
                        if result:
                            return result
            return None
        
        for rule in self.script_rules:
            result = find_in_actions(rule.get('actions', []), rule)
            if result:
                return result
        return None
    
    def _get_default_response_for_intent(self, intent: str, user_input: str) -> str:
        """为未匹配到规则的意图返回默认回复"""
        default_responses = {
            '未知': "抱歉，我没有完全理解您的问题。请告诉我您需要什么帮助？"
        }
        return default_responses.get(intent, f"抱歉，我暂时无法处理‘{intent}’。请换个问题试试。")
    
    def _match_intent(self, rule_intent: str, user_intent: str) -> bool:
        """匹配意图（支持中英文）"""
        if not rule_intent or not user_intent:
            return False
        rule_intent = rule_intent.lower()
        user_intent = user_intent.lower()
        if rule_intent == user_intent:
            return True
        intent_map = {
            'order_inquiry': '订单查询', 'order_cancel': '订单取消', 'product_info': '产品信息',
            'refund_request': '退款申请', 'complaint': '投诉', 'greeting': '问候',
            'goodbye': '告别', 'unknown': '未知', 'robot_answer': 'robot_answer',
            'human_answer': 'human_answer', 'computer': 'computer', 'phone': 'phone',
            'pad': 'pad', 'earset': 'earset'
        }
        if rule_intent in intent_map and (user_intent == intent_map[rule_intent] or user_intent == rule_intent):
            return True
        return False
    
    def _execute_state_when_rule(self, user_vars: Vars, rule: Dict, intent: str) -> str:
        """执行状态内的 WHEN 规则"""
        response_parts = []
        intent_lower = intent.lower()
        for action in rule.get('actions', []):
            if action.get('type') in ['when_respond', 'when_action']:
                if action.get('intent', '').lower() == intent_lower:
                    if action.get('type') == 'when_respond':
                        response_parts.append(action.get('content', ''))
                    elif action.get('type') == 'when_action':
                        result = self._execute_actions(user_vars, action.get('actions', []))
                        if result:
                            response_parts.append(result)
        return " ".join(response_parts) if response_parts else ""
    
    def get_user_info(self, user_name: str) -> Optional[Vars]:
        """获取用户信息"""
        return self.user_session.get_session(user_name)
    
    def get_conversation_history(self) -> List[Dict]:
        """获取对话历史"""
        return self.conversation_history
    
    def _add_to_longmemory(self, role: str, content: str, user_name: str = None):
        """添加对话到长期记忆数组"""
        memory_entry = {'role': role, 'content': content, 'timestamp': datetime.now().isoformat()}
        if user_name:
            memory_entry['user_name'] = user_name
        self.longmemory.append(memory_entry)
        if len(self.longmemory) > 100:
            self.longmemory = self.longmemory[-100:]
    
    def get_longmemory(self) -> List[Dict]:
        """获取完整的长期记忆数组"""
        return self.longmemory
    
    def clear_longmemory(self):
        """清空长期记忆"""
        self.longmemory = []

    def _extract_specific_product_response(self, user_input: str, intent: str, general_response: str) -> str:
        """从通用回复中提取针对具体产品的回复"""
        if not user_input or not general_response:
            return general_response
        user_input_lower = user_input.lower()
        products_map = {
            'computer': (['cs电脑一号', 'cs电脑二号', 'cs电脑三号'], ['CS电脑一号', 'CS电脑二号', 'CS电脑三号']),
            'phone': (['cs手机一号', 'cs手机二号', 'cs手机三号'], ['CS手机一号', 'CS手机二号', 'CS手机三号']),
            'pad': (['cs平板一号', 'cs平板二号', 'cs平板三号'], ['CS平板一号', 'CS平板二号', 'CS平板三号']),
            'earset': (['cs耳机一号', 'cs耳机二号', 'cs耳机三号'], ['CS耳机一号', 'CS耳机二号', 'CS耳机三号'])
        }
        product_lists = products_map.get(intent.lower())
        if not product_lists:
            return general_response
        
        product_list_lower, product_list_original = product_lists
        mentioned_product_original = None
        for i, p_lower in enumerate(product_list_lower):
            if p_lower in user_input_lower:
                mentioned_product_original = product_list_original[i]
                break
        
        if not mentioned_product_original:
            return general_response
        
        for line in general_response.split('\n'):
            if mentioned_product_original in line and ('：' in line or ':' in line):
                return f"关于{mentioned_product_original}：{line.split('：' if '：' in line else ':')[1].strip()}"
        
        return general_response
    
    def _sanitize_response(self, response: str) -> str:
        """清理不适用于当前系统的回复内容"""
        if not response:
            return response
        return response.replace("我的订单页面", "订单管理界面").replace("我的订单", "订单管理界面")

# 测试函数
if __name__ == "__main__":
    interpreter = DSLInterpreter(data_file='test_user_data.json')
    interpreter.load_script('''
    WHEN GREETING DO RESPOND "你好！"
    WHEN ORDER_INQUIRY DO ORDER LIST user_id
    ''')
    print(interpreter.process_user_input("test_user", "你好"))
    print(interpreter.process_user_input("test_user", "查询订单"))
    if os.path.exists('test_user_data.json'):
        os.remove('test_user_data.json')
